pp108 : Building a Custom Approval Page

Building a Custom Approval Page

This topic describes building Custom Task Details page or Custom Approval Page using the Process Platform HTML5 SDK.

You can build your own Custom Task Details page or Custom Approval Page using the Process Platform HTML5 SDK. In the Mobile Landing Page, selecting any task in the the tasks list page displays the corresponding details in the task details page. The task details page can be customized according to your requirement. A sample customapproval.htm page (which is not a stand-alone page) is included in the Process Platform HTML5 SDK for reference. For more details on Task Details or Task Approval Pages, refer to Sample Pages.

Using this Web page

This Web page can be viewed as a task by providing its URL while creating an External User Interface. For more information on creating an external user interface, refer to Creating a User Interface Using a Web Page URL.

While creating an External User Interface, you must provide the Input Schema and Output Schema definitions. Add the required elements as an input or output to this Web page.

  • The required elements may be directly added as inputs in the XML Schema. Using the defined element, you can retrieve the required information from this Web page. In the code block customapproval.htm, OrderID is the input passed from the BPM and it is used to retrieve all the Order Details. the Sample Page for Reference section is used to describe the usage of the input elements. The input elements can be accessed from the task details of the selected task as follows:

<task-details object>.TaskData.ApplicationData

  • You can include the required fields in the Output Schema definition, which must be used in the BPM or the other Process Platform components.

Sample Input Schema and Output Schema definitions can be as follows:

Input Schema definition
<xsd:schema elementFormDefault="qualified"
    targetNamespace="http://schemas.cordys.com/" xmlns=""
    xmlns:tns="http://schemas.cordys.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <element name="ApproveTask_IP" xmlns="http://www.w3.org/2001/XMLSchema">
        <complexType>
            <sequence>
                <element name="OrderID" type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
            </sequence>
        </complexType>
    </element>
</xsd:schema>
Output Schema definition
<schema attributeFormDefault="unqualified"
    elementFormDefault="qualified"
    targetNamespace="http://schemas.cordys.com/approve"
    xmlns="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://schemas.cordys.com/approve">
    <element name="ApproveTask_OP" xmlns="http://www.w3.org/2001/XMLSchema">
        <complexType>
            <sequence>
                <element name="ShipVia" type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema"/>
            </sequence>
        </complexType>
    </element>
</schema>

Accessing the task details

The taskId is passed as a URL parameter while viewing the task details page. The task details can be retrieved from the custom approval page using getTaskDetails API provided by the cordys.workflow plug-in.

Perform an action in a task

The task actions which can be performed on the task and supported by the HTML5 SDK Mobile Landing Page are displayed on the click of the Actions button. You can also define your custom actions on this Web page and execute the required action using the APIs offered by the cordys.workflow plug-in.

For example, you can have custom actions such as Approve or Reject, which can be used to perform the required action and complete the task. The required details as mentioned in the Output Schema definition can be added as taskData while performing the required action. The following is a code snippet, which performs the Complete action on the task and passes the detail ShipVia to the BPM.

$.cordys.workflow.completeTask(taskDetailModel.Task()[0], {
    ApproveTask_OP: {
        '@xmlns': 'http://schemas.cordys.com/approve',
        ShipVia: $("#fldShipVia").val()
    }
}, {dataType:'xml'}).done( function() {
    window.history.back();
});

Enabling or disabling fields according to the task status

You can enable or disable the action buttons or elements according the current status of the task. This might be required in two different scenarios as follows:

  • While navigating from the task list page to the details page
  • While performing any action using the actions button

The method refreshTaskDetailModel is called in the Mobile Landing Page (index.htm) whenever a task action is performed by clicking Actions. You can define the required action to be performed on the change of the task status. The following is a code snippet to disable the elements, when the task state is not CREATED, ASSIGNED, or INPROGRESS:

function refreshTaskDetailModel(task){
    var taskState = task.State;
    if( taskState =="CREATED" || taskState =="ASSIGNED" || taskState =="INPROGRESS"){
        // Perform desired action like enable or diable the task action button depending on the status
        //$("#controlgroup a").removeClass("ui-disabled");
    } else {
        //$("#controlgroup a").addClass("ui-disabled");
    }
}

Customizing the Page

You can display the links to show the attachments that are available on the task and the location, if available. For more information on getting the attachments and location, refer to approvetask.htm.

Sample page

The following code snippet is a sample task details page that is used to retrieve the order details, select the shipping method, and confirm the shipment:

customapproval.htm
<!DOCTYPE html>
<html>
    <head>
    <title>Approve</title>
    <meta name="viewport" content="width=device-width, initial-scale=1"/>
    <link rel="stylesheet" href="/cordys/thirdparty/jquery/cordys.min.css" type="text/css" />
    <link rel="stylesheet" href="/cordys/thirdparty/jquery/jquery.mobile.structure.min.css" type="text/css" />
    <script src="/cordys/thirdparty/jquery/jquery.js"></script>
    <script src="/cordys/thirdparty/jquery/jquery.mobile.min.js"></script>
    <script src="/cordys/thirdparty/knockout/knockout.js" type="text/javascript"></script>
    <script src="/cordys/html5/cordys.html5sdk.js" type="text/javascript"></script>
</head>
<body>
    <div data-role="page" id="approvePage">
        <div data-role="content" data-theme="c">
            <ul data-role="listview" data-inset="true">
                <li data-role="heading" data-theme="c" data-mini="true">
                    <div>
                        <a class="ui-link-inherit">
                            <h3 class="ui-li-heading">Order Details</h3> <!--  NOMBV -->
                        </a>
                    </div>
                </li>
                <li data-mini="true" id="detailView" data-bind="with: selectedItem" readonly>
                    <div>
                        <div>
                            <div><label for="fldOrderID" class="ui-input-text">OrderID</label></div>
                            <div><input id="fldOrderID" readonly class="ui-input-text ui-body-b ui-corner-all ui-shadow-inset" data-bind="value:OrderID" style="font-weight:normal"/></div>
                        </div>
                        <div>
                            <div><label for="fldOrderDate" class="ui-input-text">Order Date</label></div>
                            <div><input id="fldOrderDate" readonly class="ui-input-text ui-body-b ui-corner-all ui-shadow-inset" data-bind="value:OrderDate" style="font-weight:normal"/></div>
                        </div>
                        <div>
                            <div><label for="fldRequiredDate" class="ui-input-text">Required Date</label></div>
                            <div><input id="fldRequiredDate" readonly class="ui-input-text ui-body-b ui-corner-all ui-shadow-inset" data-bind="value:RequiredDate" style="font-weight:normal"/></div>
                        </div>
                        <div>
                            <div><label for="fldName" class="ui-input-text">Freight</label></div>
                            <div><input id="fldName" readonly class="ui-input-text ui-body-b ui-corner-all ui-shadow-inset" data-bind="value:Freight" style="font-weight:normal"/></div>
                        </div>
                        <div>
                            <div><label for="fldName" class="ui-input-text">Shipping Address</label></div>
                            <div><input id="fldName" readonly class="ui-input-text ui-body-b ui-corner-all ui-shadow-inset" data-bind="value:ShipName() + ', ' + ShipAddress() + ', ' + ShipCity() + ' - ' + ShipPostalCode() + ', ' + ShipCountry()" style="font-weight:normal"/></div>
                        </div>
                    </div>
                </li>
                <li>
                    <div>
                        <h3 class="ui-li-heading">Select Shipment Details</h3> <!--  NOMBV -->
                    </div>
                    <div>
                        <div>
                            <fieldset data-role="controlgroup" data-type="horizontal">
                                <legend>Shipping Date :</legend>
                                 
                                <label for="fldShippingDateMonth">Month</label>
                                <select name="fldShippingDateMonth" id="fldShippingDateMonth">
                                    <option>Month</option>
                                    <option value="01">January</option><option value="02">February</option><option value="03">March</option><option value="04">April</option><option value="05">May</option><option value="06">June</option><option value="07">July</option><option value="08">August</option><option value="09">September</option><option value="10">October</option><option value="11">November</option><option value="12">December</option>
                                </select>
                                 
                                <label for="fldShippingDateDay">Day</label>
                               <select name="fldShippingDateDay" id="fldShippingDateDay">
	<option>Day</option>
	<option value="01">1</option>
	<option value="02">2</option>
	<option value="03">3</option>
	<option value="04">4</option>
	<option value="05">5</option>
	<option value="06">6</option>
	<option value="07">7</option>
	<option value="08">8</option>
	<option value="09">9</option>
	<option value="10">10</option>
	<option value="11">11</option>
	<option value="12">12</option>
	<option value="13">13</option>
	<option value="14">14</option>
	<option value="15">15</option>
	<option value="16">16</option>
	<option value="17">17</option>
	<option value="18">18</option>
	<option value="19">19</option>
	<option value="20">20</option>
	<option value="21">21</option>
	<option value="22">22</option>
	<option value="23">23</option>
	<option value="24">24</option>
	<option value="25">25</option>
	<option value="26">26</option>
	<option value="27">27</option>
	<option value="28">28</option>
	<option value="29">29</option>
	<option value="30">30</option>
	<option value="31">31</option>
</select>
<label for="fldShippingDateYear">Year</label>
                                <select name="fldShippingDateYear" id="fldShippingDateYear">
                                    <option>Year</option>
                                    <option value="2013">2013</option>
                                    <option value="2014">2014</option>
                                    <option value="2015">2015</option>
                                </select>
                                 
                            </fieldset>
                        </div>
                    </div>
                    <div data-type="horizontal" data-theme="d">
                        <label for="fldShipVia" class="select">Shipping Method:</label>
                        <select name="fldShipVia" id="fldShipVia">
                            <option value="0">Select</option>
                            <option value="1">Speedy Express</option>
                            <option value="2">United Package</option>
                            <option value="3">Federal Shipping</option>
                        </select>
                    </div>
                </li>
                <li data-role="fieldcontain" data-mini="true">
                    <div id="controlgroup" data-role="controlgroup" data-type="horizontal" data-theme="d">
                        <a data-role="button" data-theme="c" onclick="completeTask()">Confirm Shipment</a>
                    </div>
                </li>
            </ul>
        </div>
    </div>
        <script type="text/javascript">
            var taskDetails, taskId = getURLParameter(window.location, "taskId");
             
            var ordersModel = new $.cordys.model({
                objectName: "Orders", // Name of the Business Object
                context : document.getElementById('detailView'), // Where the data has to be bound to
                dataType: "json",
                isReadOnly: false
            });
             
            $.cordys.json.defaults.removeNamespacePrefix = true;
             
            $("#approvePage").bind( 'pageshow',function(event, ui) {
                 
                $.cordys.workflow.getTaskDetails(taskId).done(function(task) {
                     
                    taskDetails = task;
                    var taskState = taskDetails.State ;
                    if( taskState !="CREATED" && taskState !="ASSIGNED" && taskState !="INPROGRESS"){
                        $("#controlgroup a").addClass("ui-disabled");
                    }
                     
                    // Call the read method. Getting the order details using the OrderID passed from the bpm
                    ordersModel.read({
                        namespace: "http://schemas.cordys.com/NW",
                        method: "GetOrdersObject",
                        // Parameters for the method
                        parameters: {
                            OrderID : taskDetails.TaskData.ApplicationData.ApproveTask_IP.OrderID
                        }
                    }).done(function (resposeObject) {
                        ordersModel.selectedItem(resposeObject[0]);
                    });
                });
            });
             
             
            var claimDone = false;
            function completeTask() {
                var orderModel = ordersModel.Orders();
                 
                //Checking if all the required details are entered
                if(getFormattedShippingDate() && $("#fldShipVia").val() !== "Select") {
                    //Updating the model with the details entered.
                    orderModel[0].ShippedDate(getFormattedShippingDate());
                    orderModel[0].ShipVia($("#fldShipVia").val());
                     
                    ordersModel.update({
                        namespace: "http://schemas.cordys.com/NW",
                        method: "UpdateOrders"
                    }).done(function (resposeObject) {
                        //Claiming the task if not assigned to the user
                        var Assignee = (taskDetails.Assignee) ? taskDetails.Assignee.text : taskDetails.Assignee ; //NOMBV
                        var taskStatus = taskDetails.State;
                        if (!claimDone && Assignee == "") {
                            claimDone = true;
                            $.cordys.workflow.claimTask(taskDetails, { 
                                success: function() {
                                    completeTask();
                                }
                            });
                            return;
                        }
                        //Completing the task and sending the new data back to the bpm
                        $.cordys.workflow.completeTask(taskDetails, {
                            ApproveTask_OP: {
                                '@xmlns': 'http://schemas.cordys.com/approve',
                                ShipVia: $("#fldShipVia").val()
                            }
                        }, {dataType:'xml'}).done( function() {
                            window.history.back();
                        });
                    }).fail(function(error, statusText, errorThrown) {
                        alert("Update Order Failed. Please Try again.");
                    });
                 
                } else {
                    alert("Enter all the required Shipment Details.");
                }
            }
             
            // This method is used to refresh the model once any of the action occured through the menu item. Gets called from index.htm
            function refreshTaskDetailModel(task){
                var taskState = task.State;
                if( taskState =="CREATED" || taskState =="ASSIGNED" || taskState =="INPROGRESS"){
                    $("#controlgroup a").removeClass("ui-disabled");
                } else{
                    $("#controlgroup a").addClass("ui-disabled");
                }
            }
             
            function getFormattedShippingDate(){
                if($("#fldShippingDateYear").val() !== "Year" && $("#fldShippingDateMonth").val() !== "Month" && $("#fldShippingDateDay").val() !== "Day") {
                    var formattedDate = $("#fldShippingDateYear").val() + "-" + $("#fldShippingDateMonth").val() + "-" + $("#fldShippingDateDay").val() + "T00:00:00.00";
                return formattedDate;
                } else {
                    return false;
                }
            }
        </script>
    </div>
</body>
</html>

In this Web page, the OrderID is passed from the BPM that is used to retrieve and display the order details. You can select the shipping method sent back to the BPM for updating the details. The task is completed when the user selects the confirm shipment option.

This Web page may not work independently, as it has dependencies with the other Process Platform Components.